#-*- coding: utf-8 -*-


from datetime import datetime, timedelta
from itertools import accumulate

CHINESEYEARCODE = [
    19416,
    19168,  42352,  21717,  53856,  55632,  91476,  22176,  39632,
    21970,  19168,  42422,  42192,  53840, 119381,  46400,  54944,
    44450,  38320,  84343,  18800,  42160,  46261,  27216,  27968,
    109396,  11104,  38256,  21234,  18800,  25958,  54432,  59984,
    92821,  23248,  11104, 100067,  37600, 116951,  51536,  54432,
    120998,  46416,  22176, 107956,   9680,  37584,  53938,  43344,
    46423,  27808,  46416,  86869,  19872,  42416,  83315,  21168,
    43432,  59728,  27296,  44710,  43856,  19296,  43748,  42352,
    21088,  62051,  55632,  23383,  22176,  38608,  19925,  19152,
    42192,  54484,  53840,  54616,  46400,  46752, 103846,  38320,
    18864,  43380,  42160,  45690,  27216,  27968,  44870,  43872,
    38256,  19189,  18800,  25776,  29859,  59984,  27480,  23232,
    43872,  38613,  37600,  51552,  55636,  54432,  55888,  30034,
    22176,  43959,   9680,  37584,  51893,  43344,  46240,  47780,
    44368,  21977,  19360,  42416,  86390,  21168,  43312,  31060,
    27296,  44368,  23378,  19296,  42726,  42208,  53856,  60005,
    54576,  23200,  30371,  38608,  19195,  19152,  42192, 118966,
    53840,  54560,  56645,  46496,  22224,  21938,  18864,  42359,
    42160,  43600, 111189,  27936,  44448,  84835,  37744,  18936,
    18800,  25776,  92326,  59984,  27296, 108228,  43744,  37600,
    53987,  51552,  54615,  54432,  55888,  23893,  22176,  42704,
    21972,  21200,  43448,  43344,  46240,  46758,  44368,  21920,
    43940,  42416,  21168,  45683,  26928,  29495,  27296,  44368,
    84821,  19296,  42352,  21732,  53600,  59752,  54560,  55968,
    92838,  22224,  19168,  43476,  41680,  53584,  62034,  54560
]

'''
从1900年，至2100年每年的农历春节的公历日期
'''
CHINESENEWYEAR = [
    '19000131',
    '19010219', '19020208', '19030129', '19040216', '19050204',
    '19060125', '19070213', '19080202', '19090122', '19100210',
    '19110130', '19120218', '19130206', '19140126', '19150214',
    '19160203', '19170123', '19180211', '19190201', '19200220',
    '19210208', '19220128', '19230216', '19240205', '19250124',
    '19260213', '19270202', '19280123', '19290210', '19300130',
    '19310217', '19320206', '19330126', '19340214', '19350204',
    '19360124', '19370211', '19380131', '19390219', '19400208',
    '19410127', '19420215', '19430205', '19440125', '19450213',
    '19460202', '19470122', '19480210', '19490129', '19500217',
    '19510206', '19520127', '19530214', '19540203', '19550124',
    '19560212', '19570131', '19580218', '19590208', '19600128',
    '19610215', '19620205', '19630125', '19640213', '19650202',
    '19660121', '19670209', '19680130', '19690217', '19700206',
    '19710127', '19720215', '19730203', '19740123', '19750211',
    '19760131', '19770218', '19780207', '19790128', '19800216',
    '19810205', '19820125', '19830213', '19840202', '19850220',
    '19860209', '19870129', '19880217', '19890206', '19900127',
    '19910215', '19920204', '19930123', '19940210', '19950131',
    '19960219', '19970207', '19980128', '19990216', '20000205',
    '20010124', '20020212', '20030201', '20040122', '20050209',
    '20060129', '20070218', '20080207', '20090126', '20100214',
    '20110203', '20120123', '20130210', '20140131', '20150219',
    '20160208', '20170128', '20180216', '20190205', '20200125',
    '20210212', '20220201', '20230122', '20240210', '20250129',
    '20260217', '20270206', '20280126', '20290213', '20300203',
    '20310123', '20320211', '20330131', '20340219', '20350208',
    '20360128', '20370215', '20380204', '20390124', '20400212',
    '20410201', '20420122', '20430210', '20440130', '20450217',
    '20460206', '20470126', '20480214', '20490202', '20500123',
    '20510211', '20520201', '20530219', '20540208', '20550128',
    '20560215', '20570204', '20580124', '20590212', '20600202',
    '20610121', '20620209', '20630129', '20640217', '20650205',
    '20660126', '20670214', '20680203', '20690123', '20700211',
    '20710131', '20720219', '20730207', '20740127', '20750215',
    '20760205', '20770124', '20780212', '20790202', '20800122',
    '20810209', '20820129', '20830217', '20840206', '20850126',
    '20860214', '20870203', '20880124', '20890210', '20900130',
    '20910218', '20920207', '20930127', '20940215', '20950205',
    '20960125', '20970212', '20980201', '20990121', '21000209'
]


class ZhDate():
    def __init__(self, lunar_year, lunar_month, lunar_day, leap_month=False):

        self.lunar_year = lunar_year
        self.lunar_month = lunar_month
        self.lunar_day = lunar_day
        self.leap_month = leap_month
        self.year_code = CHINESEYEARCODE[self.lunar_year - 1900]
        self.newyear = datetime.strptime(CHINESENEWYEAR[self.lunar_year - 1900], '%Y%m%d')
    
    @staticmethod
    def from_datetime(dt):

        lunar_year = dt.year
        if (datetime.strptime(CHINESENEWYEAR[lunar_year-1900], '%Y%m%d') - dt).days > 0:
            lunar_year -= 1
        newyear_dt = datetime.strptime(CHINESENEWYEAR[lunar_year-1900], '%Y%m%d')
        days_passed = (dt - newyear_dt).days
        year_code = CHINESEYEARCODE[lunar_year - 1900]
        month_days = ZhDate.decode(year_code)

        for pos, days in enumerate(accumulate(month_days)):
            if days_passed + 1 <= days:
                month = pos + 1
                lunar_day = month_days[pos] - (days - days_passed) + 1
                break

        leap_month = False
        if (year_code & 0xf) == 0 or month <= (year_code & 0xf):
            lunar_month = month
        else:
            lunar_month = month - 1

        if (year_code & 0xf) != 0 and month == (year_code & 0xf) + 1:
            leap_month = True
        
        return ZhDate(lunar_year, lunar_month, lunar_day, leap_month)

    
    def chinese(self):
        ZHNUMS = '零一二三四五六七八九十'
        zh_year = ''
        for i in range(0, 4):
            zh_year += ZHNUMS[int(str(self.lunar_year)[i])]
        zh_year += '年'

        if self.leap_month:
            zh_month = '闰'
        else:
            zh_month = ''

        if self.lunar_month == 1:
            zh_month += '正'
        elif self.lunar_month == 11:
            zh_month += '冬'
        elif self.lunar_month == 12:
            zh_month += '腊'
        elif self.lunar_month <= 10:
            zh_month += ZHNUMS[self.lunar_month]
        else:
            zh_month += "十{}".format(ZHNUMS[self.lunar_month - 10])
        zh_month += '月'

        if self.lunar_day <= 10:
            zh_day = '初{}'.format(ZHNUMS[self.lunar_day])
        elif self.lunar_day < 20:
            zh_day = '十{}'.format(ZHNUMS[self.lunar_day-10])
        elif self.lunar_day == 20:
            zh_day = '廿〇'
        elif self.lunar_day < 30:
            zh_day = '廿{}'.format(ZHNUMS[self.lunar_day - 20])
        else:
            zh_day = '三十'

        year_tiandi = '岁在' + ZhDate.__tiandi(self.lunar_year - 1900 + 36)

        shengxiao = "鼠牛虎兔龙蛇马羊猴鸡狗猪"
        
        return "{}{}{} {} ({}年)".format(zh_year,zh_month, zh_day, year_tiandi, (shengxiao[(self.lunar_year - 1900) % 12]))


    @staticmethod
    def __tiandi(anum):
        tian = '甲乙丙丁戊己庚辛壬癸'
        di = '子丑寅卯辰巳午未申酉戌亥'
        return '{}{}'.format(tian[anum % 10],di[anum % 12])

    
    @staticmethod
    def decode(year_code):
        month_days = list()
        for i in range(5, 17):
            if (year_code >> (i - 1)) & 1:
                month_days.insert(0, 30)
            else:
                month_days.insert(0, 29)
        if year_code & 0xf:
            if year_code >> 16:
                month_days.insert((year_code & 0xf), 30)
            else:
                month_days.insert((year_code & 0xf), 29)
        return month_days